package com.newlink.building.login.ui.fragments

import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.text.method.HideReturnsTransformationMethod
import android.text.method.PasswordTransformationMethod
import android.view.View
import androidx.core.content.ContextCompat
import com.newlink.building.login.R
import com.newlink.building.login.databinding.LayoutPasswordBinding
import com.newlink.building.login.event.ResetPwdEvent
import com.newlink.building.login.mvp.contract.Module_Login_InputNewPwdContract
import com.newlink.building.common_base.base.BaseMvpFragment
import com.newlink.building.common_base.ext.showToast
import com.newlink.building.common_base.ext.showToastImmediately
import com.newlink.building.common_base.model.bean.NewPasswordBean
import com.newlink.building.common_base.utils.DialogUtil
import com.newlink.building.common_base.utils.NLog
import com.newlink.building.common_base.utils.RegexUtils
import com.newlink.building.common_base.utils.logDebug
import com.newlink.building.crypt.library_crypt.digest.Md5Crypt
import com.newlink.building.obfuscation.Module_Obfuscation_ObfuscationHelper
import com.newlink.building.obfuscation.Module_Obfuscation_ObfuscationInvoker
import com.newlink.building.login.mvp.presenter.Module_Login_InputNewPwdPresenter
import org.greenrobot.eventbus.EventBus

/**
 * @Author: admin
 * @Date: 2022/9/13
 * @Description: 设置新密码页面，用于用户重置或设置账户密码。
 * @License:  Copyright  1998 Fanvil Technology Co., Ltd. All rights reserved.
 */
class Module_Login_SetPasswordFragment :
    BaseMvpFragment<Module_Login_InputNewPwdContract.View, Module_Login_InputNewPwdContract.Presenter>(),
    Module_Login_InputNewPwdContract.View {

    // 视图绑定实例
    private lateinit var binding: LayoutPasswordBinding

    // 验证成功的邮箱或手机号
    private var verificationTarget: String = ""

    // 等待对话框
    private val loadingDialog by lazy {
        DialogUtil.getWaitDialog(requireContext())
    }

    /**
     * Companion object 用于提供Fragment实例。
     */
    companion object {
        // Bundle中用于传递邮箱或手机号的键
        private const val ARG_VERIFY_TARGET: String = "VERIFY_EMAIL" // 保持原名，但语义扩展为验证目标

        /**
         * 获取SetPasswordFragment的新实例。
         * @param emailOrMobile 邮箱地址或手机号码，取决于重置流程。
         * @return SetPasswordFragment实例。
         */
        fun getInstance(emailOrMobile: String): Module_Login_SetPasswordFragment {
            val fragment = Module_Login_SetPasswordFragment()
            val bundle = Bundle().apply {
                putString(ARG_VERIFY_TARGET, emailOrMobile)
            }
            fragment.arguments = bundle
            return fragment
        }
    }

    /**
     * 获取传递给Fragment的参数（邮箱或手机号）。
     * 这是一个辅助方法，方便在ForgetPwdEmailActivity中判断是否需要重新创建Fragment。
     */
    fun getArgumentParam(): String {
        return arguments?.getString(ARG_VERIFY_TARGET, "") ?: ""
    }

    /**
     * 绑定布局文件并返回根视图。
     */
    override fun attachLayoutRes(): View {
        binding = LayoutPasswordBinding.inflate(layoutInflater)
        return binding.root
    }

    /**
     * 创建Presenter实例。
     */
    override fun createPresenter(): Module_Login_InputNewPwdContract.Presenter = Module_Login_InputNewPwdPresenter()

    /**
     * 初始化视图组件和设置监听器。
     */
    override fun initView(view: View) {
        // 设置新密码页面初始化时的混淆
        Module_Obfuscation_ObfuscationHelper.onMethodEnter("SetPasswordFragment", "initView")
        Module_Obfuscation_ObfuscationInvoker.invokeRandom("set_password")

        // 从arguments中获取验证目标（邮箱或手机号）
        verificationTarget = requireArguments().getString(ARG_VERIFY_TARGET, "")

        // 设置EditText的背景资源
        binding.etPassword.setBackgroundResource(R.drawable.et_underline_selector)
        binding.etConfirmPassword.setBackgroundResource(R.drawable.et_underline_selector)

        setupPasswordVisibilityToggle()
        setupClearButtons()
        setupTextWatchers()
        setupConfirmButtonListener()
    }

    /**
     * 设置密码显示/隐藏切换功能。
     */
    private fun setupPasswordVisibilityToggle() {
        binding.ibEye.isEnabled = false // 默认眼睛图标为禁用状态（密码隐藏）
        binding.linearPwdDisplay.setOnClickListener {
            val isCurrentlyVisible = binding.ibEye.isEnabled // ibEye.isEnabled 表示当前是否可见
            binding.etPassword.transformationMethod =
                if (isCurrentlyVisible) PasswordTransformationMethod.getInstance() else HideReturnsTransformationMethod.getInstance()
            binding.etConfirmPassword.transformationMethod =
                if (isCurrentlyVisible) PasswordTransformationMethod.getInstance() else HideReturnsTransformationMethod.getInstance()
            binding.ibEye.isEnabled = !isCurrentlyVisible // 切换眼睛图标状态
        }
    }

    /**
     * 设置清除按钮的点击事件。
     */
    private fun setupClearButtons() {
        binding.ivPasswordNewClear.setOnClickListener {
            binding.etPassword.text?.clear()
        }
        binding.ivPasswordConfirmClear.setOnClickListener {
            binding.etConfirmPassword.text?.clear()
        }
    }

    /**
     * 设置密码输入框的文本变化监听器。
     */
    private fun setupTextWatchers() {
        binding.etPassword.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
            override fun afterTextChanged(s: Editable?) {
                updateButtonAndClearIconState()
            }
        })

        binding.etConfirmPassword.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
            override fun afterTextChanged(s: Editable?) {
                updateButtonAndClearIconState()
            }
        })
    }

    /**
     * 设置确认按钮的点击事件和密码验证逻辑。
     */
    private fun setupConfirmButtonListener() {
        binding.btnRegisterConfirm.setOnClickListener {
            val newPassword = binding.etPassword.text?.toString()
            val confirmPassword = binding.etConfirmPassword.text?.toString()

            if (newPassword.isNullOrEmpty()) {
                binding.etPassword.error = resources.getString(R.string.user_reset_pwd_error_format)
                return@setOnClickListener
            }
            if (confirmPassword.isNullOrEmpty()) {
                binding.etConfirmPassword.error =
                    resources.getString(R.string.user_reset_pwd_error_format)
                return@setOnClickListener
            }
            if (newPassword != confirmPassword) {
                showConfirmPasswordMismatchError(true)
                return@setOnClickListener
            }

            if (newPassword.length !in 8..36) {
                showToast(getString(R.string.set_password_length))
                return@setOnClickListener
            }
            if (!RegexUtils.checkPassword(newPassword)) {
                showToast(getString(R.string.set_password_length))
                return@setOnClickListener
            }

            NLog.e("新密码: $newPassword")
            NLog.e("确认密码: $confirmPassword")

            // 对密码进行MD5加密
            val hashedPwd1 = Md5Crypt.md5(newPassword)
            val hashedPwd2 = Md5Crypt.md5(newPassword) // 确认密码也用相同方式加密以匹配API要求

            NLog.e("MD5加密后的密码1: $hashedPwd1")
            NLog.e("MD5加密后的密码2: $hashedPwd2")

            loadingDialog.show() // 显示加载对话框

            // 根据验证目标的类型（邮箱或手机号）发送不同的请求
            val passwordBean = if (RegexUtils.checkEmail2(verificationTarget)) {
                NewPasswordBean(hashedPwd1, hashedPwd2, email = verificationTarget)
            } else {
                NewPasswordBean(
                    hashedPwd1,
                    hashedPwd2,
                    mobile = verificationTarget,
                    area = countryCode
                )
            }
            mPresenter?.sendNewPwd(passwordBean)
        }
    }

    /**
     * 显示或隐藏确认密码不匹配的错误提示。
     * @param showError 是否显示错误提示。
     */
    fun showConfirmPasswordMismatchError(showError: Boolean) {
        binding.linearPwdDifferent.visibility = if (showError) View.VISIBLE else View.GONE
        binding.linearPwdRule.visibility = if (showError) View.GONE else View.VISIBLE // 规则提示与错误提示互斥
        // 根据错误状态设置下划线的颜色
        val lineColorRes = if (showError) R.color.red else R.color.color_e2e2e8
        binding.viewLine1.background = ContextCompat.getDrawable(requireContext(), lineColorRes)
        binding.viewLine2.background = ContextCompat.getDrawable(requireContext(), lineColorRes)
    }

    /**
     * 根据输入框内容更新确认按钮和清除图标的状态。
     */
    fun updateButtonAndClearIconState() {
        showConfirmPasswordMismatchError(false) // 每次输入时隐藏错误提示

        val newPasswordInput = binding.etPassword.text?.trim().toString()
        val confirmPasswordInput = binding.etConfirmPassword.text?.trim().toString()

        binding.ivPasswordNewClear.visibility =
            if (newPasswordInput.isNotEmpty()) View.VISIBLE else View.GONE
        binding.ivPasswordConfirmClear.visibility =
            if (confirmPasswordInput.isNotEmpty()) View.VISIBLE else View.GONE

        // 只有当两个密码输入框都有内容时，确认按钮才可用
        binding.btnRegisterConfirm.isEnabled =
            newPasswordInput.isNotEmpty() && confirmPasswordInput.isNotEmpty()
    }

    /**
     * 生命周期回调：Fragment被附加到Activity时。
     */
    override fun onAttach(context: Context) {
        super.onAttach(context)
    }

    /**
     * 懒加载方法，当前未实现具体逻辑。
     */
    override fun lazyLoad() {
        // 无需额外的懒加载逻辑
    }

    /**
     * 设置新密码成功回调。
     * 显示成功Toast，通过EventBus发送重置密码成功事件，并隐藏加载对话框。
     */
    override fun setNewPwdSuccess() {
        showToastImmediately(R.string.set_password_success)
        logDebug<Module_Login_SetPasswordFragment>("set password success")
        EventBus.getDefault().post(ResetPwdEvent(true))
        loadingDialog.dismiss()
    }

    /**
     * 设置新密码失败回调。
     * 显示失败原因Toast，并隐藏加载对话框。
     * @param reason 失败原因的字符串。
     */
    override fun setNewPwdFailed(reason: String?) {
        logDebug<Module_Login_SetPasswordFragment>("set password failed")
        reason?.let {
            showToastImmediately(it)
        }
        loadingDialog.dismiss()
    }
}